'use strict';

module.exports = core;

const fs = require('fs');
const path = require('path');
const semver = require('semver');
const colors = require('colors/safe');
const userHome = require('user-home');
const npm = require('@imooc-cli-dev-liu/get-npm-info')
const init = require('@imooc-cli-dev-liu/init')
const log = require('@imooc-cli-dev-liu/log')
const exec = require('@imooc-cli-dev-liu/exec')
const program = require('commander');

const {
  LOWEST_NODE_VERSION,
  DEFAULT_CLI_HOME,
  NPM_NAME,
  DEPENDENCIES_PATH,
} = require('./const'); 

let args;
let config;

const pkg = require('../package.json')

async function prepare() {
  checkPkgVersion()
	checkRoot()
	checkUserHome()
	checkInputArgs()
	checkEnv()
  await checkGlobalUpdate(); // 检查工具是否需要更新
}


async function core() {
  try {
    await prepare()
  registerCommand()
  } catch (error) {
    log.error(e.message)
    if(program.debug) {
      console.log(e)
    }
  }
  
}

function registerCommand() {
  program
    .name(Object.keys(pkg.bin)[0])
    .version(pkg.version)
    .usage('<command> [options]')
    .option('-d, --debug', '是否开启调试模式', false)
    .option('-tp, --targetPath <targetPath>', '是否指定本地调试文件路劲', '');

  program
    .command('init [projectName]')
    .option('-f, --force', '是否强制初始化项目')
    .action(exec)
  
  program.on('option:targetPath', function() {
    process.env.CLI_TARGET_PATH = program.targetPath
  })

  // program
  //   .command('learn')
  //   .description('访问课程链接')
  //   .action(() => {
  //     log.success('欢迎学习', '慕课网前端架构师课程');
  //   });

  // program
  //   .command('init [type]')
  //   .description('项目初始化')
  //   .option('--packagePath <packagePath>', '手动指定init包路径')
  //   .option('--force', '覆盖当前路径文件（谨慎使用）')
  //   .action(async (type, { packagePath, force }) => {
  //     const packageName = '@imooc-cli/init';
  //     const packageVersion = '1.0.0';
  //     await execCommand({ packagePath, packageName, packageVersion }, { type, force });
  //   });

  // program
  //   .command('publish')
  //   .description('项目发布')
  //   .option('--packagePath <packagePath>', '手动指定publish包路径')
  //   .option('--refreshToken', '强制更新git token信息')
  //   .option('--refreshOwner', '强制更新git owner信息')
  //   .option('--refreshServer', '强制更新git server信息')
  //   .option('--force', '强制更新所有缓存信息')
  //   .option('--prod', '正式发布')
  //   .option('--keepCache', '保留缓存')
  //   .option('--cnpm', '使用cnpm')
  //   .option('--buildCmd <buildCmd>', '手动指定build命令')
  //   .option('--sshUser <sshUser>', '模板服务端用户名')
  //   .option('--sshIp <sshIp>', '模板服务器IP或域名')
  //   .option('--sshPath <sshPath>', '模板服务器上传路径')
  //   .action(async ({
  //                    packagePath,
  //                    refreshToken,
  //                    refreshOwner,
  //                    refreshServer,
  //                    force,
  //                    prod,
  //                    sshUser,
  //                    sshIp,
  //                    sshPath,
  //                    keepCache,
  //                    cnpm,
  //                    buildCmd,
  //                  }) => {
  //     const packageName = '@imooc-cli/publish';
  //     const packageVersion = '1.0.0';
  //     if (force) {
  //       refreshToken = true;
  //       refreshOwner = true;
  //       refreshServer = true;
  //     }
  //     await execCommand({ packagePath, packageName, packageVersion }, {
  //       refreshToken,
  //       refreshOwner,
  //       refreshServer,
  //       prod,
  //       sshUser,
  //       sshIp,
  //       sshPath,
  //       keepCache,
  //       cnpm,
  //       buildCmd,
  //     });
  //   });

  // program
  //   .command('replace')
  //   .description('作业网站优化')
  //   .option('--packagePath <packagePath>', '手动指定replace包路径')
  //   .option('--region <region>', 'oss region')
  //   .option('--bucket <bucket>', 'oss bucket')
  //   .option('--ossAccessKey <ossAccessKey>', 'oss accessKey')
  //   .option('--ossSecretKey <ossSecretKey>', 'oss secretKey')
  //   .action(async ({ packagePath, region, bucket, ossAccessKey, ossSecretKey }) => {
  //     const packageName = '@imooc-cli/replace';
  //     const packageVersion = '1.0.0';
  //     await execCommand({ packagePath, packageName, packageVersion }, { region, bucket, ossAccessKey, ossSecretKey });
  //   });

  // program
  //   .command('clean')
  //   .description('清空缓存文件')
  //   .option('-a, --all', '清空全部')
  //   .option('-d, --dep', '清空依赖文件')
  //   .action((options) => {
  //     log.notice('开始清空缓存文件');
  //     if (options.all) {
  //       cleanAll();
  //     } else if (options.dep) {
  //       const depPath = path.resolve(config.cliHome, DEPENDENCIES_PATH);
  //       if (fs.existsSync(depPath)) {
  //         fse.emptyDirSync(depPath);
  //         log.success('清空依赖文件成功', depPath);
  //       } else {
  //         log.success('文件夹不存在', depPath);
  //       }
  //     } else {
  //       cleanAll();
  //     }
  //   });

  program
    // .option('--debug', '打开调试模式')
    .parse(process.argv);

  if (args._.length < 1) {
    program.outputHelp();
  }
}

async function execCommand({ packagePath, packageName, packageVersion }, extraOptions) {
  let rootFile;
  try {
    if (packagePath) {
      const execPackage = new Package({
        targetPath: packagePath,
        storePath: packagePath,
        name: packageName,
        version: packageVersion,
      });
      rootFile = execPackage.getRootFilePath(true);
    } else {
      const { cliHome } = config;
      const packageDir = `${DEPENDENCIES_PATH}`;
      const targetPath = path.resolve(cliHome, packageDir);
      const storePath = path.resolve(targetPath, 'node_modules');
      const initPackage = new Package({
        targetPath,
        storePath,
        name: packageName,
        version: packageVersion,
      });
      if (await initPackage.exists()) {
        await initPackage.update();
      } else {
        await initPackage.install();
      }
      rootFile = initPackage.getRootFilePath();
    }
    const _config = Object.assign({}, config, extraOptions, {
      debug: args.debug,
    });
    if (fs.existsSync(rootFile)) {
      const code = `require('${rootFile}')(${JSON.stringify(_config)})`;
      const p = exec('node', ['-e', code], { 'stdio': 'inherit' });
      p.on('error', e => {
        log.verbose('命令执行失败:', e);
        handleError(e);
        process.exit(1);
      });
      p.on('exit', c => {
        log.verbose('命令执行成功:', c);
        process.exit(c);
      });
    } else {
      throw new Error('入口文件不存在，请重试！');
    }
  } catch (e) {
    log.error(e.message);
  }
}

function checkRoot() {
	const rootCheck = require('root-check');
	rootCheck(colors.red('请避免使用 root 账户启动本应用'));
}

function checkUserHome() {
  if (!userHome || !fs.existsSync(userHome)) {
    throw new Error(colors.red('当前登录用户主目录不存在！'));
  }
}
function checkInputArgs() {
  const minimist = require('minimist');
  args = minimist(process.argv.slice(2)); // 解析查询参数
  checkArgs(args); // 校验参数
}

function checkArgs(args) {
  if (args.debug) {
    process.env.LOG_LEVEL = 'verbose';
  } else {
    process.env.LOG_LEVEL = 'info';
  }
  log.level = process.env.LOG_LEVEL;
}

function checkPkgVersion () {
	log.notice('cli', pkg.version)
}

function checkEnv() {
  const dotenv = require('dotenv');
  dotenv.config({
    path: path.resolve(userHome, '.env'),
  });
  config = createCliConfig(); // 准备基础配置
}

function createCliConfig() {
  const cliConfig = {
    home: userHome,
  };
  if (process.env.CLI_HOME) {
    cliConfig['cliHome'] = path.join(userHome, process.env.CLI_HOME);
  } else {
    cliConfig['cliHome'] = path.join(userHome, DEFAULT_CLI_HOME);
  }
  process.env.CLI_HOME_PATH = cliConfig.cliHome;
  return cliConfig;
}

async function checkGlobalUpdate() {
  const currentVersion = pkg.version;
	const lastVersion = await npm.getNpmSemverVersion(NPM_NAME, currentVersion);
  if (lastVersion && semver.gt(lastVersion, currentVersion)) {
    log.warn(colors.yellow(`请手动更新 ${NPM_NAME}，当前版本：${pkg.version}，最新版本：${lastVersion}
                更新命令： npm install -g ${NPM_NAME}`));
  }
}